﻿using System;
using System.Windows.Forms;
using Microsoft.TeamFoundation.VersionControl.Client;
using System.Collections.Generic;

namespace SLCustomPolicies
{
	[Serializable]
	public class EnsureLatestPolicy : PolicyBase
	{
		#region Private Variables (Includes information strings)

		private readonly string _policyType = "Ensure Latest Version Policy";
		private readonly string _policyDescription = "This policy ensures that users are editing the latest version of their files";
		private readonly string _policyInstallationInstructions = "Please see web based installation instructions";
		private readonly string _policyTypeDescription = "Ensure Latest Version Policy Description";
		private readonly string _policyHelp = "Please get latest version of your files before checking them in.";
		private readonly string _activateMessage = "Please get latest version of your files before checking them in.";

		private PolicyFailureType _failureType = PolicyFailureType.OnePerFile;

		#endregion

		#region Information Methods and Properties

		public override string Type
		{
			get
			{
				return this._policyType;
			}
		}

		public override string Description
		{
			get
			{
				return this._policyDescription;
			}
		}

		public override string TypeDescription
		{
			get
			{
				return this._policyTypeDescription;
			}
		}

		public override string InstallationInstructions
		{
			get
			{
				return this._policyInstallationInstructions;
			}
		}

		#endregion

		#region Help and Activate

		public override void DisplayHelp(PolicyFailure failure)
		{
			MessageBox.Show(this._policyHelp);
		}

		/// <summary>
		/// This method is called whenever a user clicks the policy failure in the Pending Changes Window - List of policy failures.
		/// </summary>
		/// <param name="failure"></param>
		public override void Activate(PolicyFailure failure)
		{
			//This method allows us to use some GUI for the user to be able to fix the offending files.
			//I have chosen not to do this.  Instead, I simply show a messagebox.
			MessageBox.Show(this._activateMessage, "Get Latest Version");
		}

		#endregion

		#region Edit Policy

		public override bool CanEdit
		{
			get
			{
				return true;
			}
		}

		/// <summary>
		/// Provides the GUI, allowing the administrator to change policy options.
		/// </summary>
		/// <param name="policyEditArgs"></param>
		/// <returns></returns>
		public override bool Edit(IPolicyEditArgs policyEditArgs)
		{
			EditPolicy ep = new EditPolicy();
			ep.FailureType = _failureType;

			if (ep.ShowDialog() == DialogResult.OK)
			{
				//Because policies are serialized, there is no need to save configuration in a config file
				_failureType = ep.FailureType;
			}

			return true;
		}

		#endregion

		#region Evaluate on CheckedPendingChangesChanged

		public override void Initialize(IPendingCheckin pendingCheckin)
		{
			base.Initialize(pendingCheckin);

			//Adding this even handler allows us to reevaluate whenever a developer checks or unchecks a file in the pending changes window.
			pendingCheckin.PendingChanges.CheckedPendingChangesChanged += OnCheckedPendingChangesChanged;
		}

		void OnCheckedPendingChangesChanged(object sender, EventArgs e)
		{
			base.OnPolicyStateChanged(Evaluate());
		}

		#endregion

		public override PolicyFailure[] Evaluate()
		{
			List<PolicyFailure> failures = new List<PolicyFailure>();

			ItemSpec[] items = ItemSpec.FromPendingChanges(PendingCheckin.PendingChanges.CheckedPendingChanges);

			if (items.Length > 0)
			{
				ExtendedItem[][] extItems = PendingCheckin.PendingChanges.Workspace.GetExtendedItems(items, DeletedState.NonDeleted, ItemType.File);

				foreach (ExtendedItem[] extItem in extItems)
				{
					foreach (ExtendedItem item in extItem)
					{
						if (item.IsInWorkspace && item.ChangeType == ChangeType.Edit && !item.IsLatest)
						{
							if (_failureType == PolicyFailureType.OneTotal)
							{
								return new PolicyFailure[] { new PolicyFailure("Get latest version of all files.", this) };
							}
							else
							{
								failures.Add(new PolicyFailure("Get latest version: " + item.LocalItem, this));
							}
						}
					}
				}
			}

			return failures.ToArray();
		}
	}
}
